package com.sau.pixelcart.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sau.pixelcart.common.exception.AccountException;
import com.sau.pixelcart.common.exception.BusinessException;
import com.sau.pixelcart.common.properties.EmailProperties;
import com.sau.pixelcart.common.result.PageResult;
import com.sau.pixelcart.common.utils.MailUtil;
import com.sau.pixelcart.domain.dto.UserDTO;
import com.sau.pixelcart.domain.dto.UserEmailDTO;
import com.sau.pixelcart.domain.dto.UserPageDTO;
import com.sau.pixelcart.domain.dto.UserRoleDTO;
import com.sau.pixelcart.domain.entity.User;
import com.sau.pixelcart.domain.entity.UserRole;
import com.sau.pixelcart.domain.vo.UserRoleVO;
import com.sau.pixelcart.domain.vo.UserVO;
import com.sau.pixelcart.mapper.UserMapper;
import com.sau.pixelcart.mapper.UserRoleMapper;
import com.sau.pixelcart.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 用户账户信息表 服务实现类
 * </p>
 *
 * @author Inton
 * @since 2025-03-08
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private EmailProperties emailProperties;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 用户登录
     * @param userDTO
     * @return
     */
    @Override
    public User login(UserDTO userDTO) {
        //验证用户信息
        String username = userDTO.getUsername();
        String password = userDTO.getPassword();

        //根据用户名或邮箱查询数据库中对应的User
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(StringUtils.isNotBlank(username),  User::getUsername, username)
                .or()
                .eq(StringUtils.isNotBlank(username),  User::getEmail, username);
        User user = baseMapper.selectOne(lambdaQueryWrapper);

        //处理异常
        if(user == null){
            throw new AccountException("账号信息不存在");
        }

        //设置加密对比
        String passwordMd5 = DigestUtils.md5DigestAsHex(password.getBytes());
        if(!passwordMd5.equals(user.getPassword())){
            throw new AccountException("密码错误");
        }

        if(user.getStatus().equals("locked")){
            throw new AccountException("账号已锁定");
        }
        return user;
    }

    /**
     * 用户注册
     * @param userDTO
     * @return
     */
    @Override
    public User register(UserDTO userDTO) {
        //判断用户名和邮箱是否存在，若存在抛出异常
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getUsername, userDTO.getUsername())
                .or()
                .eq(User::getEmail, userDTO.getEmail());
        User userInfo = userMapper.selectOne(lambdaQueryWrapper);

        //都不存在，设置用户初始化信息
        if(userInfo != null){
            throw new AccountException("账号信息已存在，无法注册");
        }
        //添加到表中，并返回该注册成功的user
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        //设置加密存储密码
        user.setPassword(DigestUtils.md5DigestAsHex(userDTO.getPassword().getBytes()));
        user.setRegistrationTime(LocalDateTime.now());
        user.setStatus("active");
        user.setRole("user");
        user.setAgreedToTerms(true);
        userMapper.insert(user);

        return user;
    }

    /**
     * 记录用户上一次登录时间
     * @param userId
     */
    @Override
    public void setLoginTime(String userId) {
        LocalDateTime nowTime = LocalDateTime.now();
        userMapper.setLoginTime(userId,nowTime);
    }

    /**
     * 修改密码
     * @param userDTO
     */
    @Override
    public void changePassword(UserDTO userDTO) {
        String oldPassword = userDTO.getOldPassword();
        User user = userMapper.selectById(userDTO.getUserId());

        //校验旧密码输入是否正确
        if(!DigestUtils.md5DigestAsHex(oldPassword.getBytes()).equals(user.getPassword())){
            throw new AccountException("原密码不符");
        }

        String newPasswordMd5 = DigestUtils.md5DigestAsHex(userDTO.getNewPassword().getBytes());
        //将更新后的user写入数据库中
        userMapper.changePassword(user.getUserId(),newPasswordMd5);
        log.info("密码修改完成...");
    }

    /**
     * 用户分页查询
     * @param userPageDTO
     * @return
     */
    @Override
    public PageResult<UserVO> pageQuery(UserPageDTO userPageDTO) {
        //开始分页
        Page<User> page = new Page<>(userPageDTO.getPage(), userPageDTO.getPageSize());

        //查询条件
        LambdaQueryWrapper<User> userWrapper = new LambdaQueryWrapper<>();
        if(userPageDTO.getKeyword() != null){
            userWrapper.like(User::getUsername,userPageDTO.getKeyword())
                    .or()
                    .like(User::getEmail,userPageDTO.getKeyword());
        }


        Page<User> userPage = userMapper.selectPage(page, userWrapper);

        PageResult<UserVO> pageResult = new PageResult<>();
        BeanUtils.copyProperties(userPage,pageResult);

        return pageResult;
    }

    /**
     * 删除用户
     * @param userId
     */
    @Override
    public void deleteById(String userId) {
        //判断当前用户身份
        log.info("删除当前用户");
        User user = userMapper.selectById(userId);
        if(user.getRole().equals("admin")){
            throw new AccountException("无法删除管理员账户");
        }
        //执行删除
        userMapper.deleteById(userId);
    }

    /**
     * 重设用户密码
     * @param userId
     */
    @Override
    public void resetPassword(String userId) {
        userMapper.resetPassword(userId);
    }

    /**
     * 修改用户状态
     * @param userDTO
     */
    @Override
    public void changeStatus(UserDTO userDTO) {
        String status = userDTO.getStatus();
        User user = userMapper.selectById(userDTO.getUserId());

        user.setStatus(status);
        userMapper.updateById(user);
    }

    /**
     * 权限分页查询
     * @param userPageDTO
     * @return
     */
    @Override
    public PageResult<UserRoleVO> pageRule(UserPageDTO userPageDTO) {
        Page<UserRole> page = new Page<>(userPageDTO.getPage(), userPageDTO.getPageSize());
        LambdaQueryWrapper<UserRole> roleWrapper = new LambdaQueryWrapper<>();
        Page<UserRole> userRolePage = userRoleMapper.selectPage(page, roleWrapper);

        PageResult<UserRoleVO> pageResult = new PageResult<>();
        BeanUtils.copyProperties(userRolePage,pageResult);

        return pageResult;
    }

    /**
     * 启用/停用role
     * @param userRoleDTO
     */
    @Override
    public void changeRoleStatus(UserRoleDTO userRoleDTO) {
        if(userRoleDTO.getRoleType().equals("admin")){
            throw new BusinessException("管理员账户无法停用");
        }
        UserRole userRole = new UserRole();
        BeanUtils.copyProperties(userRoleDTO,userRole);
        userRoleMapper.updateById(userRole);
    }

    /**
     * 发送邮箱验证码
     * @param email
     */
    @Override
    public void sendCode(String email) {
        String code = "";

        Random random = new Random();
        for (int i = 0; i < 6; i++) {
            Integer number = random.nextInt(9);
            code += number;
        }

        //邮件标题
        String title = "云栈智慧管家";
        //文本内容
        String content = "【验证码】您的验证码是："+ code + "，如非本人操作，请忽略此邮件。五分钟之内有效。";

        boolean flag = MailUtil.sendMail(emailProperties,email,title,content);
//        userMapper.update(email,code);

        if(flag){
            //验证码存入redis中，5分钟内有效
            int time = 60 * 5;
            redisTemplate.opsForValue().set("userEmail_" + email, code, time, TimeUnit.SECONDS);
        }else{
            throw new BusinessException("邮件发送失败");
        }

    }

    /**
     * 校验邮箱验证码
     * @param userEmailDTO
     * @return
     */
    @Override
    public boolean checkCode(UserEmailDTO userEmailDTO) {
        String email = userEmailDTO.getEmail();
        String code = userEmailDTO.getCode();
        if(code.equals(redisTemplate.opsForValue().get("userEmail_" + email))){
            //验证码正确
            return true;
        }else{
            return false;
        }

    }

    /**
     * 邮箱找回密码
     * @param userEmailDTO
     */
    @Override
    public void setPasswordByEmail(UserEmailDTO userEmailDTO) {
        String email = userEmailDTO.getEmail();

        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getEmail,email);
        User user = userMapper.selectOne(userLambdaQueryWrapper);
        if(user == null){
            throw new AccountException("该用户不存在");
        }
        user.setPassword(DigestUtils.md5DigestAsHex(userEmailDTO.getPassword().getBytes()));
        userMapper.updateById(user);
    }

    /**
     * 检查邮箱是否存在
     * @param userEmailDTO
     * @return
     */
    @Override
    public boolean checkEmail(UserEmailDTO userEmailDTO) {
        String email = userEmailDTO.getEmail();
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getEmail,email);
        User user = userMapper.selectOne(userLambdaQueryWrapper);

        return (user != null && user.getEmail().equals(email));
    }

}
